﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Neural; // for Neural.MLPerceptron
using Computing; // for Computing.Vector 
using Probability; // ror Probability.Sampler 

namespace CsharpNN
{
    class Program
    {
        static void Main(string[] args)
        {
            Neural.MLPerceptron2 perceptron = new MLPerceptron2();
            perceptron.Build(2, CellType.Arcustangent, new int[] { 40, 2 });
            // 10 Arcustangenet neurons in the first layer and 
            // 2 linear neurons in the second layer 
            Vector averages = new Vector(new double[] { 0, 0 });
            Vector stddevs = new Vector(new double[] { 1, 1 });
            perceptron.SetInputDescription(averages, stddevs); // scaling the inputs 
            perceptron.InitWeights();

            ASampler sampler = new ASampler(); 

            Vector input = new Vector(2);
            Vector output = new Vector(2); 
            Vector output_d = new Vector(2);
            Vector dq_doutput = null;
            Vector dq_dweights = null;
            double sum_of_errors = 0; 

            for (int i = 1; true; i++)
            {
                input[0] = sampler.SampleFromNormal(0, 1);
                input[1] = sampler.SampleFromNormal(0, 1);

                output_d[0] = Math.Sin(input[0] * 4 + input[1] * 3);
                output_d[1] = Math.Cos(input[0] * 3 - input[1] * 4);

                perceptron.Approximate(input, ref output);

                dq_doutput = output - output_d;

                perceptron.BackPropagateGradient(dq_doutput, ref dq_dweights); // only makes sense after Apprximate 

                perceptron.AddToWeights(dq_dweights, -1e-2); // theta := theta -1e-2 * dq_dweights 

                sum_of_errors += dq_doutput * dq_doutput; 

                if ((i % 1000) == 0)
                {
                    System.Console.WriteLine(i.ToString() + ", err=" + Math.Sqrt(sum_of_errors / 1000));
                    sum_of_errors = 0; 
                }
            }
        }
    }
}
